import moment from 'moment';
import { TRMessage } from '#/components';
import { HttpCode } from '#/utils/contacts';
import { getStationLevelThree } from '@/services/user';
import {
  postQueryProvinceList,
  fetchSequences,
  fetchDetail,
  listShortTermTradTactics,
  getTradeSequence,
  shanxiShortTermTradDecision,
} from '@/pages/Tianji/DayRollingTradeStrategy/services';
import { EchartsType } from './constant';
import { fetchTradeTime } from './services';
import { buildPower, getTreeByCodes } from '@/utils';

let timeout;
const delay = (time) => new Promise((resolve) => setTimeout(resolve, time));
const delayClear = (time) =>
  new Promise((resolve) => {
    clearTimeout(timeout);
    timeout = setTimeout(resolve, time);
  });

export default {
  namespace: 'dayRollingTradeStragety',
  state: {
    loadingNum: 0, // 全局loading效果
    tradeCenterTime: null, // 交易中心时间
    marketList: [],
    provinceId: null,
    tradeDate: moment(), // 当前交易日期
    // tradeDate: moment('2025-06-05'), // 当前交易日期
    tradeSeqList: [], // 交易序列列表
    tradeSeqId: null, // 当前交易序列id
    originStations: [], // 全部场站（平铺）
    convertResultTreeData: [], // 场站转换树形数据
    stations: [], // 某个省份的场站

    stationId: null, // 当前交易单元id
    strategyId: null, // 策略id

    searchStationId: null, // 搜索的场站id
    // 交易策略时点数据
    hourOrderList: [],
    selectedRowKeys: [], // 选择的时点行
    selectedEcharts: EchartsType.THREE_DIMENSION, // 选择的图形
    strategyPowerType: null, // 策略计算电量展示口径
    echartsHourOrder: 1, // echarts图对应的时段
    echartsHourOrderItem: null, // echarts图对应的时段信息
    echartsBenefit: 100, // 收益变动目标
    echartsPrice: null, // 电价目标
    echartsPower: null, // 电量目标
    echartsBenefitStep: 300, // 收益截面精度
    echartsRefreshTag: 0, // echarts图形刷新标识
    forceConflict: false, // 当前出力数据源设置是否和用户的全局设置冲突
    priceConflict: false, // 当前价格数据源是否和全局的冲突
    capacity: 0, // 装机容量
    upperPrice: 0, // 上限价
    lowerPrice: 0, // 下限价

    marketValueStr: null,
    XJTableData: [], // 新疆表格数据
    declareList: [], // 交易策路编辑

    nxRefresh: undefined,
    headerLoading: false,

    tableDataIsSave: '0', // 策略保存状态

    tableLimitPower: null, // 限电量
    forecastPowerV: '暂无', // 预测出力版本提示
    forecastPriceV: '暂无', // 预测现货电价版本提示
    historyQuantityV: '', // 日滚历史成交电量版本默认值
    historyQuantityList: [], // 日滚历史成交电量历史版本下拉
    transactionPowerV: '', // 交易电量版本默认值
    transactionPowerList: [], // 交易电量历史版本下拉
    transactionPriceType: null, // 交易价格版本默认值
    forecastDate: null, // 预测日期
    newVersionData: [], // 新版本数据
    version1: null, // 预测出力设置弹窗版本
    version2: null, // 现货价格预测设置版本
    version3: '1', // 是否自主调整版本
  },
  reducers: {
    setVersion1(state, { payload }) {
      return { ...state, version1: payload };
    },

    setVersion2(state, { payload }) {
      return { ...state, version2: payload };
    },

    setVersion3(state, { payload }) {
      return { ...state, version3: payload };
    },

    setNewVersionData(state, { payload }) {
      return { ...state, newVersionData: payload };
    },

    setForecastDate(state, { payload }) {
      return { ...state, forecastDate: payload };
    },

    setHistoryQuantityV(state, { payload }) {
      return { ...state, historyQuantityV: payload };
    },

    setHistoryQuantityList(state, { payload }) {
      return { ...state, historyQuantityList: payload };
    },

    setTransactionPowerV(state, { payload }) {
      return { ...state, transactionPowerV: payload };
    },

    setTransactionPowerList(state, { payload }) {
      return { ...state, transactionPowerList: payload };
    },

    setTransactionPriceType(state, { payload }) {
      return { ...state, transactionPriceType: payload };
    },

    setForecastPowerV(state, { payload }) {
      return { ...state, forecastPowerV: payload };
    },
    setForecastPriceV(state, { payload }) {
      return { ...state, forecastPriceV: payload };
    },
    setTableLimitPower(state, { payload }) {
      return { ...state, tableLimitPower: payload };
    },
    setTableDataIsSave(state, { payload }) {
      return { ...state, tableDataIsSave: payload };
    },
    setAddLoadingNum(state) {
      return { ...state, loadingNum: state.loadingNum + 1 };
    },
    setSubLoadingNum(state) {
      return { ...state, loadingNum: state.loadingNum - 1 };
    },
    setTradeCenterTime(state, { payload }) {
      return { ...state, tradeCenterTime: payload };
    },
    setProvinceId(state, { payload }) {
      return { ...state, provinceId: payload };
    },
    setTradeDate(state, { payload }) {
      return { ...state, tradeDate: payload };
    },
    setTradeSeqList(state, { payload }) {
      return { ...state, tradeSeqList: payload };
    },
    /**
     * 修改交易序列id时，交易单元设置为默认值
     * @param {*} state
     * @param {*} param1
     * @returns
     */
    setTradeSeqId(state, { payload }) {
      return {
        ...state,
        tradeSeqId: payload,
        // stationId: state.stations[0]?.value,
      };
    },
    setOriginStations(state, { payload }) {
      return { ...state, originStations: payload };
    },
    setStations(state, { payload }) {
      return { ...state, stations: payload };
    },
    setSearchStationId(state, { payload }) {
      return { ...state, searchStationId: payload };
    },
    setStationId(state, { payload }) {
      return { ...state, stationId: payload };
    },
    setStrategyId(state, { payload }) {
      return { ...state, strategyId: payload };
    },
    setHourOrderList(state, { payload }) {
      return { ...state, hourOrderList: payload };
    },
    setSelectedRowKeys(state, { payload }) {
      return { ...state, selectedRowKeys: payload };
    },
    setSelectedEcharts(state, { payload }) {
      return { ...state, selectedEcharts: payload };
    },
    setStrategyPowerType(state, { payload }) {
      return { ...state, strategyPowerType: payload };
    },
    setEchartsHourOrder(state, { payload }) {
      return { ...state, echartsHourOrder: payload };
    },
    setEchartsHourOrderItem(state, { payload }) {
      return { ...state, echartsHourOrderItem: payload };
    },
    setEchartsBenefit(state, { payload }) {
      return { ...state, echartsBenefit: payload };
    },
    setEchartsPrice(state, { payload }) {
      return { ...state, echartsPrice: payload };
    },
    setEchartsPower(state, { payload }) {
      return { ...state, echartsPower: payload };
    },
    setEchartsBenefitStep(state, { payload }) {
      return { ...state, echartsBenefitStep: payload };
    },
    setEchartsRefreshTag(state) {
      return { ...state, echartsRefreshTag: state.echartsRefreshTag + 1 };
    },
    setForceConflict(state, { payload }) {
      return { ...state, forceConflict: payload };
    },
    setPriceConflict(state, { payload }) {
      return { ...state, priceConflict: payload };
    },
    setCapacity(state, { payload }) {
      return { ...state, capacity: payload };
    },
    setUpperPrice(state, { payload }) {
      return { ...state, upperPrice: payload };
    },
    setLowerPrice(state, { payload }) {
      return { ...state, lowerPrice: payload };
    },
    setMarketList(state, { payload }) {
      return { ...state, marketList: payload };
    },
    setMarketId(state, { payload }) {
      return { ...state, marketId: payload };
    },
    setConvertResultTreeData(state, { payload }) {
      const marketIdMap = new Map();
      const treeData = [];
      function getStations(arr, marketId, groupId) {
        const stations = [];
        for (let i = 0; i < arr.length; i++) {
          const n = arr[i];
          if (groupId && groupId === n.groupId && n.marketId === marketId) {
            stations.push({
              title: n.stationName,
              key: n.stationId,
            });
          }
          if (!groupId && n.marketId === marketId) {
            stations.push({
              stationId: n.stationId,
              stationName: n.stationName,
              stationType: n.stationType,
            });
          }
        }

        return _.uniqBy(stations, groupId ? 'key' : 'stationId');
      }
      function getTreeDataChild(arr, marketId) {
        const treeData = [];
        for (let i = 0; i < arr.length; i++) {
          const item = arr[i];
          const key = `${item.marketId}-${item.groupId}`;
          const index = _.findIndex(treeData, (n) => n.key === key);
          if (item.marketId === marketId && index < 0) {
            treeData.push({
              title: item.groupName,
              key: key,
              children: getStations(arr, marketId, item.groupId),
            });
          }
        }
        return treeData;
      }
      for (let i = 0; i < payload.length; i++) {
        const item = payload[i];
        if (!marketIdMap.has(item.marketId)) {
          marketIdMap.set(item.marketId, true);
          treeData.push({
            title: item.marketName,
            key: item.marketId,
            children: getTreeDataChild(payload, item.marketId),
          });
        }
      }
      return { ...state, convertResultTreeData: treeData };
    },
    setMarketValueStr(state, { payload }) {
      return { ...state, marketValueStr: payload };
    },
    setXJTableData(state, { payload }) {
      return { ...state, XJTableData: payload };
    },
    setDeclareList(state, { payload }) {
      return { ...state, declareList: payload };
    },

    setNxRefresh(state, { payload }) {
      return { ...state, nxRefresh: payload };
    },
    setHeaderLoading(state, { payload }) {
      return { ...state, headerLoading: payload };
    },
  },
  effects: {
    // 每隔30s同步交易中心时间
    *fetchTradeTimeEffect({ payload }, { call, put, select }) {
      const res = yield call(fetchTradeTime);
      if (res?.statusCode === HttpCode.SUCCESS) {
        yield put({
          type: 'setTradeCenterTime',
          payload: moment(res?.data?.time),
        });
        yield put({
          type: 'updateTradeTimeEffect',
        });
      } else {
        TRMessage.error(res?.message || '获取交易中心时间失败');
      }
      yield delay(30 * 1000);
      yield put({
        type: 'fetchTradeTimeEffect',
      });
    },
    // 每隔一秒更新交易中心时间
    *updateTradeTimeEffect({ payload }, { call, put, select }) {
      yield delayClear(1 * 1000);
      let currentState = yield select((_) => _.dayRollingTradeStragety);
      let time = moment(currentState.tradeCenterTime);
      time.add(1, 's');
      yield put({
        type: 'setTradeCenterTime',
        payload: moment(time),
      });
      yield put({
        type: 'updateTradeTimeEffect',
      });
    },
    // 获取省份列表
    *fetchProvincesEffect({ payload }, { call, put, select }) {
      yield put({
        type: 'setAddLoadingNum',
      });
      let global = yield select((_) => _.global);
      const res = yield call(postQueryProvinceList, global.configure.menuCode);
      yield put({
        type: 'setSubLoadingNum',
      });
      if (res?.statusCode === HttpCode.SUCCESS) {
        const marketList = getTreeByCodes(['market', 'group', 'station'], res?.json).treeOptions;
        const _stations = _.uniqBy(
          res?.json?.map((i) => ({
            ...i,
            label: i.stationName,
            value: i.stationId,
          })),
          'stationId',
        );
        yield put({
          type: 'setOriginStations',
          payload: _stations,
        });
        yield put({
          type: 'setMarketList',
          payload: marketList,
        });
        yield put({
          type: 'setMarketId',
          payload: marketList[0].value,
        });
        yield put({
          type: 'setProvinceId',
          payload: marketList[0].provinceId,
        });
      } else {
        TRMessage.error(res?.message || '获取省份列表失败');
      }
    },
    // 获取交易序列
    *fetchSequencesEffect({ payload }, { call, put, select }) {
      yield put({
        type: 'setStationId',
        payload: payload.stationId,
      });
      let tradeDate = yield select((_) => _.dayRollingTradeStragety.tradeDate);
      yield put({
        type: 'setAddLoadingNum',
      });
      const res = yield call(getTradeSequence, {
        ...payload,
        date: tradeDate.format('YYYY-MM-DD'),
      });
      yield put({
        type: 'setSubLoadingNum',
      });
      if (res?.statusCode === HttpCode.SUCCESS) {
        let sequenceList = res?.data;
        if (sequenceList.length) {
          sequenceList.forEach((sequence) => {
            // let arr = sequence.tradeSequenceName.match(/^.*\((\d+)-(\d+)-(\d+)\)$/);
            // sequence.simpleName = `${arr[1]}年${arr[2]}月${arr[3]}日日滚动交易`;
            sequence.simpleName = sequence.tradeSequenceName;
          });
          yield put({
            type: 'setTradeSeqList',
            payload: sequenceList,
          });
          yield put({
            type: 'setTradeSeqId',
            payload: sequenceList[0].tradeSequenceId,
          });
        } else {
          yield put({
            type: 'initDataEffect',
          });
        }
      } else {
        yield put({
          type: 'initDataEffect',
        });
        TRMessage.error(res?.message || '获取交易序列失败');
      }
    },
    // 获取交易单元列表
    *getStationLevelThreeEffect({ payload }, { call, put, select }) {
      yield put({
        type: 'setAddLoadingNum',
      });
      let global = yield select((_) => _.global);
      const res = yield call(getStationLevelThree, global.configure.menuCode);
      yield put({
        type: 'setSubLoadingNum',
      });

      if (res?.statusCode === HttpCode.SUCCESS) {
        let data = res.data;
        let _stations = [];
        data.forEach((x) => {
          // 省份
          (x?.children || []).map((y) => {
            // 公司
            (y?.children || []).map((z) => {
              // 场站
              _stations.push(z);
            });
          });
        });
        _stations = _stations.sort((a, b) =>
          a.label.substr(0, 1).localeCompare(b.label.substr(0, 1)),
        );
        yield put({
          type: 'setOriginStations',
          payload: _stations,
        });

        // yield put({
        //   type: 'setStationId',
        //   payload: _stations[0]?.value,
        // });
      } else {
        TRMessage.error(res?.message || '获取交易单元信息失败');
      }
    },
    // 获取策略详情
    *fetchDetailEffect({ payload }, { call, put, select }) {
      let dayRollingTradeStragety = yield select((_) => _.dayRollingTradeStragety);
      let menuCode = yield select((_) => _.global.configure.menuCode);
      let tradeDate = yield select((_) => _.dayRollingTradeStragety.tradeDate);
      function getForecastDateByTradeSeqId(tradeSeqId, tradeSeqList) {
        const matchedItem = tradeSeqList.find((item) => item.tradeSequenceId === tradeSeqId);

        return matchedItem ? matchedItem.forecastDate : null;
      }

      yield put({
        type: 'setAddLoadingNum',
      });
      const params = {
        date: getForecastDateByTradeSeqId(
          dayRollingTradeStragety.tradeSeqId,
          dayRollingTradeStragety.tradeSeqList,
        ),
        marketId: 'PHBSX',
        stationId: payload.stationId,
        tradeSequenceId: dayRollingTradeStragety.tradeSeqId,
      };
      yield put({
        type: 'setForecastDate',
        payload: params.date,
      });
      const res = yield call(shanxiShortTermTradDecision, params);
      yield put({
        type: 'setSubLoadingNum',
      });
      if (res?.statusCode === HttpCode.SUCCESS) {
        // 清空选中的时点
        yield put({
          type: 'setSelectedRowKeys',
          payload: [],
        });

        let hourOrderList = res?.data?.modelDataList || [];
        let versionData = res?.data?.versionData || {};
        yield put({
          type: 'setNewVersionData',
          payload: versionData,
        });
        // 提取版本数据
        const {
          forecastPowerV,
          forecastPriceV,
          limitPowerType = '1',
          historyQuantityV,
          historyQuantityList = [],
          transactionPowerV,
          transactionPowerList = [],
          transactionPriceType,
        } = versionData;

        /* hourOrderList.forEach((item) => {
          item.strategyPower =
            item.strategyPower === null ? null : parseFloat(item.strategyPower.toFixed(3));
          item.strategyPrice =
            item.strategyPrice === null ? null : parseFloat(item.strategyPrice.toFixed(2));
          item.strategyBenefitsChange =
            item.strategyBenefitsChange === null
              ? null
              : parseFloat(item.strategyBenefitsChange.toFixed(2));
        }); */

        yield put({
          type: 'setTableLimitPower',
          payload: limitPowerType,
        });

        yield put({
          type: 'setForecastPowerV',
          payload: forecastPowerV,
        });

        yield put({
          type: 'setForecastPriceV',
          payload: forecastPriceV,
        });

        yield put({
          type: 'setHistoryQuantityV',
          payload: historyQuantityV,
        });

        yield put({
          type: 'setHistoryQuantityList',
          payload: historyQuantityList,
        });

        yield put({
          type: 'setTransactionPowerV',
          payload: transactionPowerV,
        });

        yield put({
          type: 'setTransactionPowerList',
          payload: transactionPowerList,
        });

        yield put({
          type: 'setTransactionPriceType',
          payload: transactionPriceType,
        });

        yield put({
          type: 'setHourOrderList',
          payload: hourOrderList,
        });

        yield put({
          type: 'setTableDataIsSave',
          payload: res?.data?.versionData.saveStatus,
        });

        yield put({
          type: 'setStrategyPowerType',
          payload: res?.data?.strategyPowerType,
        });

        yield put({
          type: 'setEchartsHourOrder',
          payload: 1,
        });
        yield put({
          type: 'setEchartsHourOrderItem',
          payload: hourOrderList?.[0] || {},
        });
        yield put({
          type: 'initEchartsDataEffect',
          payload: hourOrderList?.[0] || {},
        });
        yield put({
          type: 'setForceConflict',
          payload: res?.data?.forceConflict || false,
        });
        yield put({
          type: 'setPriceConflict',
          payload: res?.data?.priceConflict || false,
        });
        yield put({
          type: 'setCapacity',
          payload: res?.data?.capacity || 0,
        });
        yield put({
          type: 'setUpperPrice',
          payload: hourOrderList?.[0]?.upperPrice || 0,
        });
        yield put({
          type: 'setLowerPrice',
          payload: hourOrderList?.[0]?.lowerPrice || 0,
        });

        /**
         * 设置策略id要放在获取冲突数据后面，因为需要监听策略id的变化获取冲突数据
         * 这个方式可以解决问题，但是太脆弱了，后续考虑用更坚韧的方案解决类似问题
         */
        yield put({
          type: 'setStrategyId',
          payload: res?.data?.strategyId,
        });
      } else {
        yield put({
          type: 'setHourOrderList',
          payload: [],
        });
        yield put({
          type: 'setStrategyId',
          payload: null,
        });
        yield put({
          type: 'setEchartsRefreshTag',
        });
        TRMessage.error(res?.message || '获取策略详情失败');
      }
    },
    // 初始化三个截面图默认目标值，收益截面精度默认值，初始化默认选中图形
    *initEchartsDataEffect({ payload }, { call, put, select }) {
      yield put({
        type: 'setSelectedEcharts',
        payload: EchartsType.THREE_DIMENSION,
      });

      yield put({
        type: 'setEchartsBenefit',
        payload: 100,
      });
      yield put({
        type: 'setEchartsPrice',
        payload: (() => {
          let price = payload.forecastPrice;
          if (price > payload.upperPrice) {
            price = payload.upperPrice;
          }
          if (price < payload.lowerPrice) {
            price = payload.lowerPrice;
          }
          return price;
        })(),
      });
      yield put({
        type: 'setEchartsPower',
        payload: (payload.forecastForce * 0.8 - payload.holdings).toFixed(3),
      });

      yield put({
        type: 'setEchartsBenefitStep',
        payload: 300,
      });
    },
    // 未获取到交易序列时，初始化部分数据
    *initDataEffect({ payload }, { call, put, select }) {
      yield put({
        type: 'setTradeSeqList',
        payload: [],
      });
      yield put({
        type: 'setTradeSeqId',
        payload: null,
      });
      yield put({
        type: 'setStrategyId',
        payload: null,
      });
    },
    // 获取新疆数据
    *fetchXJDataEffect({ payload }, { call, put, select }) {
      yield put({
        type: 'setDeclareList',
        payload: [],
      });
      yield put({
        type: 'setXJTableData',
        payload: [],
      });

      const dataFiltration = (data) => {
        const [newData, summaryItems] = data.reduce(
          (acc, item) => {
            item.timeOrderName.includes('汇总') ? acc[1].push(item) : acc[0].push(item);
            return acc;
          },
          [[], []],
        );
        return [...newData, ...summaryItems];
      };

      const getChildrenKeys = (data, marketId) => {
        const market = data.find((item) => item.key === marketId);
        if (!market) return [];
        return (
          market.children?.flatMap(
            (category) =>
              category.children?.map((child) => ({
                label: child.title,
                value: child.key,
              })) || [],
          ) || []
        );
      };

      let tradeDate = yield select((_) => _.dayRollingTradeStragety.tradeDate);
      let convertResultTreeData = yield select(
        (_) => _.dayRollingTradeStragety.convertResultTreeData,
      );
      let marketValue =
        payload != null ? payload : getChildrenKeys(convertResultTreeData, 'PXBXJ')[0]?.value;
      const params = {
        date: tradeDate.format('YYYY-MM-DD'),
        marketId: 'PXBXJ',
        stationId: marketValue,
      };
      yield put({
        type: 'setMarketValueStr',
        payload: marketValue,
      });
      yield put({
        type: 'setAddLoadingNum',
      });
      const res = yield call(listShortTermTradTactics, params);

      if (res?.statusCode === HttpCode.SUCCESS) {
        yield put({
          type: 'setXJTableData',
          // payload: dataFiltration(res?.data),
          payload: res?.data,
        });
      } else {
        TRMessage.error(res?.message || '获取交易序列失败');
      }
      yield put({
        type: 'setSubLoadingNum',
      });
    },
  },
};
